<?php
/**
 * Created by PhpStorm.
 * User: 小蛮哼哼哼
 * Email: 243194993@qq.com
 * Date: 2022/3/23
 * Time: 15:47
 * motto: 现在的努力是为了小时候吹过的牛逼！
 */

namespace app\api\controller\v1;

use app\common\business\BusOrder;
use app\common\business\BusSearchUser;
use app\common\lib\ArrClass;
use app\common\model\BuddhaOrder;
use app\common\lib\Radom;
use app\common\lib\Show;
use app\common\lib\Status;
use app\common\lib\Time;
use app\common\model\CouponCoupon;
use app\common\model\CouponReceive;
use app\common\model\MallCart;
use app\common\model\MallCateCart;
use app\common\model\MallCollect;
use app\common\model\MallGoods;
use app\common\model\MallGoodsSku;
use app\common\model\MallOrder;
use app\common\model\MallOrderGoods;
use app\common\model\MallSearchUser;
use app\common\model\MallShop;
use app\common\model\MallUserAddress;
use app\common\model\PointReceive;
use app\common\model\PointSource;
use app\common\model\WeixinExpress;
use app\common\model\WeixinExpressConfig;
use app\common\model\WeixinExpressOrder;
use app\common\model\WeixinExpressOrderList;
use Htlove\Str;
use think\App;
use think\Exception;
use think\facade\Cache;
use think\facade\Log;

class Order extends Base
{
    protected $model = null;

    public function __construct(App $app)
    {
        parent::__construct($app);
        $this->model = new MallOrder();
    }

    protected function initialize()
    {
        if (empty($this->shop_id)) {
            return Show::json_show(Status::mini_error, "请选择店铺");
        }
        parent::initialize(); // TODO: Change the autogenerated stub
    }

    /**
     * @return array|\think\response\Json|void
     */
    public function setOrderData()
    {
        $type = $this->request->param('type', 0, 'intval');
        $money = $this->request->param('money', '', 'trim');
        $mark = $this->request->param('mark', '', 'trim');
        $openid = $this->request->param('openid', '', 'trim');
        if ($type == 0) {
            return Show::json_show(Status::mini_error, "请选择捐款类型");
        }
        if (!$money) {
            return Show::json_show(Status::mini_error, "请输入捐款金额");
        }
        if (!empty($mark)) {
            $mark = htmlspecialchars($mark);
        }
        if (empty($openid)) {
            return Show::json_show(Status::mini_error, "用户信息不存在");
        }
        $data = [
            "cate_id" => $type,
            "money" => $money,
            "mark" => $mark,
            "openid" => $openid,
            "order_id" => Radom::create_trade_no()
        ];
        try {
            $res = (new BuddhaOrder())->save($data);
        } catch (\Exception $e) {
            return Show::json_show(Status::mini_error, "内部错误");
        }
        if ($res) {
            //进行支付
        } else {
            return Show::json_show(Status::mini_error, "内部异常 ");
        }
    }

    /**
     * @return array|\think\response\Json
     */
    public function getOrderByUserList()
    {
        $openid = $this->request->param('openid', "", "trim");
        if (empty($openid)) {
            return Show::json_show(Status::mini_error, "用户信息错误");
        }
        $datetime = $this->request->param('datetime', '', 'trim');
        $day = "本月";
        $where = [];
        if (!empty($datetime)) {
            $y = date('Y', $datetime / 1000);
            $m = date('m', $datetime / 1000);
            $time = Time::startTimeToEndTime($y, $m);
            $where[] = [
                ['o.create_time', "between", $time]
            ];
            if (date('Y-m', $datetime / 1000) != date('Y-m')) {
                $day = date('Y-m', $datetime / 1000) . "月";
            }
        }
//        dump($where);exit();


        try {
            $lists = (new BuddhaOrder())
                ->field("o.id,o.order_id,o.cate_id,o.money,o.create_time,c.id,c.title,o.create_time")
                ->alias('o')
                ->join('buddha_cate c', 'o.cate_id = c.id')
                ->where("openid", $openid)
                ->where($where)
                ->where('payment', 1)->paginate(10)->toArray();
        } catch (\Exception $e) {
            return Show::json_show(Status::mini_error, "订单错误");
        }
        return Show::json_show(Status::mini_normal, "ok", [
            "row" => $lists,
            "day" => $day
        ]);
    }

    /**
     * 立即购买 创建订单
     * @return array|\think\response\Json
     * @throws \think\Exception
     */
    public function directOrderToBuy()
    {
        if (!$this->request->isPost()) {
            return Show::json_show(Status::mini_error, "请求错误");
        }
        $num = $this->request->param('buynum', 1, 'intval');
        $sku_id = $this->request->param('goods_id', 0, 'intval');
        if ($sku_id == 0) {
            return Show::json_show(Status::mini_error, "内部异常");
        }

        //创建订单
        $order_id = Str::instance()->create_trade_no();
        $GoodsSkuObj = new MallGoodsSku();
        $goodsSku = $GoodsSkuObj->getBaseById($sku_id, '*,specs_value_ids as GetSpecsValue', 'goods');

        if (empty($goodsSku)) {
            return Show::json_show(Status::mini_error, "商品信息不存在");
        }
        $goods = $goodsSku['goods'];
        if (empty($goods)) {
            return Show::json_show(Status::mini_error, "商品不存在");
        }
        if ($goodsSku['status'] != 1) {
            return Show::json_show(Status::mini_error);
        }
        if ($goodsSku['stock'] < 1) {
            return Show::json_show(Status::mini_error, "商品库存不足");
        }
        $money = sysconfig('shop', 'order_money');
        if (floatval($goodsSku['price'] * $num) < floatval($money)) {
            return Show::json_show(Status::mini_error, "订单需要满{$money}才能购买");
        }
        $this->model->startTrans();
        try {
            //添加库存
            $insert_data = [
                "ordersn" => $order_id,
                "openid" => $this->m_openid,
                "orderprice" => $goodsSku['price'] * $num,
                "payprice" => $goodsSku['price'] * $num,
                "shop_id" => $this->shop_id
            ];
            $order_ids = $this->model->insertSaveById($insert_data);
            $insert_order = [
                "order_id" => $order_ids,
                "goods_id" => $goodsSku['goods_id'],
                "option_id" => $goodsSku['id'],
                "image" => $goodsSku['image'],
                "goods_name" => $goods['title'],
                "price" => $goods['price'],
                "total" => $num,
            ];
            (new MallOrderGoods())->insertSaveById($insert_order);
            $GoodsSkuObj->setStockByDec($goodsSku['id'], false, $num);
            $this->model->commit();
        } catch (\Exception $e) {
            $this->model->rollback();
            return Show::json_show(Status::mini_error, "内部异常");
        }
        return Show::json_show(Status::mini_normal, "ok", [
            "order_id" => $order_id
        ]);
    }

    /**
     * 购物车点击购买
     * @return array|\think\response\Json
     */
    public function directOrderToCart()
    {
        $ids = $this->request->param('ids', '', '');
        $type = $this->request->param('type', 1, 'intval');

        //查询商品
        if ($type == 1) {
            if (empty($ids)) {
                return Show::json_show(Status::mini_error, "请选择商品");
            }
            try {
                $cart = (new MallCart())->getCartByIds($ids, $this->m_openid);
            } catch (\Exception $e) {
                return Show::json_show(Status::mini_error, $e->getMessage());
            }
            if (empty($cart)) {
                return Show::json_show(Status::mini_error, "商品不存在");
            }
        } else if ($type == 2) {
            try {
                $cart = (new MallCateCart())->getCartByIds($this->m_openid, $this->shop_id);
            } catch (\Exception $e) {
                return Show::json_show(Status::mini_error, $e->getMessage());
            }
            if (empty($cart)) {
                return Show::json_show(Status::mini_error, "商品不存在");
            }
        }
        $order_id = Str::instance()->create_trade_no();
        $this->model->startTrans();
        try {
            $insert_data = [
                "ordersn" => $order_id,
                "openid" => $this->m_openid,
                "orderprice" => 0,
                "payprice" => 0,
                "shop_id" => $this->shop_id
            ];
            foreach ($cart as $v) {
                $insert_data['orderprice'] += $v['goods_price'] * $v['total'];
                $insert_data['payprice'] += $v['goods_price'] * $v['total'];
            }
            $money = sysconfig('shop', 'order_money');
            if (floatval($insert_data['payprice']) < floatval($money)) {
                throw new Exception("订单需要满{$money}才能起送");
            }
            $ins_id = $this->model->insertSaveById($insert_data);
            if (!$ins_id) {
                throw new Exception("创建错误");
            }
            $insert_order = [];
            foreach ($cart as $v) {
                $insert_order[] = [
                    "order_id" => $ins_id,
                    "goods_id" => $v['goods_id'],
                    "option_id" => $v['option_id'],
                    "option_name" => "",
                    "image" => $v['goodsSku']['image'],
                    "goods_name" => $v['goods']['title'],
                    "price" => $v['goodsSku']['price'],
                    "total" => $v['total'],
                    "create_time" => time()
                ];
            }
            if (empty($insert_order)) {
                throw new Exception("订单错误");
            }
            $result = (new MallOrderGoods())->insertAll($insert_order);
            //减少商品库存
            (new MallGoodsSku())->updateStockByData($insert_order);
            //删除购物车
            if ($type == 1) {
                (new MallCart())->destroy($ids, true);
            } else if ($type == 2) {
                $ids = array_column($cart, 'id');
                (new MallCateCart())->destroy($ids, true);
            }
            $this->model->commit();
        } catch (\Exception $e) {

            $this->model->rollback();
            return Show::json_show(Status::mini_error, $e->getMessage());
        }
        return Show::json_show(Status::mini_normal, "ok", [
            "order_id" => $order_id
        ]);
    }

    /**
     * 确认订单
     * @return array|\think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function confirmOrder()
    {
        if (!$this->request->isPost()) {
            return Show::json_show(Status::mini_error, "请求类型错误");
        }
        $order_id = $this->request->param('order_id', '', 'trim');
        if (empty($order_id)) {
            return Show::json_show(Status::mini_error, "订单号不存在");
        }
        //根据订单号查询订单
        $order = $this->model->getOrderByOrderId($order_id, 'id,ordersn,orderprice,payprice,status,discountprice');
        if (!$order) {
            return Show::json_show(Status::mini_error, "商品不存在");
        }
        if ($order['status'] != 0) {
            return Show::json_show(Status::mini_error, "订单状态错误");
        }
        //获取位置
        $address = (new MallUserAddress())->getUserAddressByDefaultInfo($this->m_openid);
        if ($address) {
            $address = $address->toArray();
        } else {
            $address = [];
        }
        $order['address'] = $address;
        $order_data = $this->goodsList($order);
        //获取优惠券信息
//        $goods = array_column($order_data['goods_data'], 'goods_ids');
//
//        $goods_list = [];
//        foreach ($goods as $k => $v) {
//            foreach ($v as $vv) {
//                $goods_list[] = $vv;
//            }
//        }
        $coupon = (new CouponReceive())->getUserCouponReceiveByOpenidList($this->m_openid);
        $coupon_list = [];
        foreach ($coupon as $k => $v) {
            $coupon_list[$k] = $v;
        }
        $order_data['coupon'] = $coupon_list;
        //查询满减
        $config = (new WeixinExpressConfig())->getBaseById(1);
        $order_data['express_money'] = $config['money'] ?? 0;
        $order_data['express_price'] = $config['price'] ?? 0;
        //查询用户剩余积分
        $integral = (new PointReceive())->getUserIntegralSurplus($this->m_openid);
        $money = 0;
        if ($integral != 0) {
            $num_money = $integral / sysconfig('shop', "order_integral");
            $money = $num_money * 0.01;
        }
        $order_data['integral_money'] = round($money, 2);
        $order_data['discountprice'] = $order_data['discountprice'] + $order_data['integral_money'];
        //查询剩余快递次数
        $n = (new WeixinExpress())->getUserExpressSurplus($this->m_openid);
        $order_data['express_n'] = $n;
        return Show::json_show(Status::mini_normal, 'OK', $order_data);
    }

    /**
     * 获取订单商品信息
     * @param array $order
     * @return array
     * @throws Exception
     */
    protected function goodsList(array $order = []): array
    {
        //查询订单商品
        try {
            $orderGoods = (new MallOrderGoods())->getOrderGoodsByOrderIdAll($order['id']);
        } catch (\Exception $e) {
            throw new Exception($e->getMessage());
        }
        //查询商品信息
        if (!empty($orderGoods)) {
            foreach ($orderGoods as $k => $v) {
                $orderGoods[$k] = $v;
                $goods = (new MallGoods())->where('id', $v['goods_id'])->find();

                if ($goods) {
                    $goods = $goods->toArray();
                } else {
                    $goods = [
                        "title" => $v['goods_name'],
                        "image" => $v['image'],
                        "id" => $v['id']
                    ];
                }

                $orderGoods[$k]['goods'] = $goods;
            }
        }

        //根据商品id查询商品信息
        $goods_ids = array_column($orderGoods, 'goods_id');

        $goods = (new MallGoods())->getGoodsByIds($goods_ids);

        $lists = [];
        if (!empty($goods)) {
            foreach ($goods as $v) {
                $lists[$v['id']] = $v;
            }
        }
        $row = [];
        if (!empty($lists)) {
            foreach ($orderGoods as $k => $v) {
                $row[$lists[$v['goods_id']]['shop']['id']]['name'] = $lists[$v['goods_id']]['shop']['title'];
                $row[$lists[$v['goods_id']]['shop']['id']]['logo'] = $lists[$v['goods_id']]['shop']['logo'];
                $row[$lists[$v['goods_id']]['shop']['id']]['mobile'] = $lists[$v['goods_id']]['shop']['mobile'];
                $row[$lists[$v['goods_id']]['shop']['id']]['lat'] = $lists[$v['goods_id']]['shop']['lat'];
                $row[$lists[$v['goods_id']]['shop']['id']]['lng'] = $lists[$v['goods_id']]['shop']['lng'];
                $row[$lists[$v['goods_id']]['shop']['id']]['address'] = $lists[$v['goods_id']]['shop']['address'];
                $row[$lists[$v['goods_id']]['shop']['id']]['goods_ids'][] = $v['goods_id'];
                $row[$lists[$v['goods_id']]['shop']['id']]['list'][] = [
                    "title" => $lists[$v['goods_id']]['title'],
                    "logo" => $lists[$v['goods_id']]['logo'],
                    "option_name" => $v['option_name'],
                    "price" => $v['price'],
                    "total" => $v['total'],
                    "goods_id" => $v['goods_id'],
                ];
            }
        } else {
            foreach ($orderGoods as $k => $v) {
                $row[]['list'][] = [
                    'title' => $v['goods_name'],
                    'logo' => $v['image'],
                    "option_name" => $v['option_name'],
                    "price" => $v['price'],
                    "total" => $v['total'],
                    "goods_id" => $v['goods_id'],
                ];
            }

        }
        $order['goods_data'] = $row;
        return $order;
    }

    /**
     * 查询优惠券是否可以使用
     * @return array|\think\response\Json
     * @throws Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getOrderByCoupon()
    {
        $coupon_id = $this->request->param('coupon_id', 0, 'intval');
        $order_id = $this->request->param('order_id', '', 'trim');
        //根据订单号查询订单
        if (empty($order_id)) {
            return Show::json_show(Status::mini_error, "错误");
        }
        $order = $this->model->getOrderByOrderId($order_id);
        if (!$order) {
            return Show::json_show(Status::mini_error, "订单错误");
        }
        //查询优惠券
        try {
            $this->getCoupon($coupon_id, $order['id'], $order['payprice']);
        } catch (\Exception $e) {
            return Show::json_show(Status::mini_error, $e->getMessage());
        }
        return Show::json_show(Status::mini_normal, "ok");
    }

    /**
     * 验证优惠券
     * @param int $coupon_id 用户优惠券id
     * @param int $order_id
     * @param float $money 订单金额
     * @return array
     * @throws Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    protected function getCoupon(int $coupon_id = 0, int $order_id = 0, float $money = 0): array
    {
        $orderGoods = (new MallOrderGoods())->getOrderGoodsByOrderIdAll($order_id);
        if (!$orderGoods) {
            return Show::json_show(Status::mini_error, "商品不存在");
        }
        $goods_id = array_column($orderGoods, 'goods_id');
        $coupon_receive = (new CouponReceive())->getBaseById($coupon_id, 'id,coupon_id,end_time', 'coupon');
        if (!$coupon_receive) {
            throw new Exception("不存在优惠券");
        }
        if (time() > $coupon_receive['end_time']) {
            throw new Exception("优惠券已过期");
        }
        //查询优惠券
        //判断是否指定商品
        if ($coupon_receive['coupon']['use_type'] == 2) {
            $coupon_goods = explode(',', $coupon_receive['coupon']['goods_list']);
            if (is_array($goods_id)) {
                $arr_intersect = array_intersect($goods_id, $coupon_goods);
                if (empty($arr_intersect)) {
                    throw new Exception("该优惠券不能使用");
                }
            }
            if (is_string($goods_id)) {
                if (!in_array($goods_id, $coupon_goods)) {
                    throw new Exception("该优惠券不能使用");
                }
            }
        }
        //判断券类型
        if ($coupon_receive['coupon']['type'] == 1) {
            if ($money < $coupon_receive['coupon']['money']) {
                throw new Exception("该优惠券不能使用");
            }
        }
        return $coupon_receive;
    }

    /**
     * 提交订单 支付订单
     * @return array|\think\response\Json
     * @throws Exception
     */
    public function submitOrderData()
    {
        $type = $this->request->param('type', 0, 'intval');
        $address_id = $this->request->param('address_id', 0, 'intval');
        $coupon_id = $this->request->param('coupon_id', 0, 'intval');
        $desc = $this->request->param('desc', '', 'trim');
        $order_id = $this->request->param('order_id', '', 'trim');
        $express = $this->request->param('express');
        $input_value = $this->request->param('input_value');
        $input_value1 = $this->request->param('input_value1');
        $input_value2 = $this->request->param('input_value2');
        if (!empty($input_value)) {
            foreach ($input_value as $k => $v) {
                $express[] = $input_value[$k] . " - " . $input_value1[$k] . " - " . $input_value2[$k];
            }
        }
        if ($type == 0) {
            if ($address_id == 0) {
                return Show::json_show(Status::mini_error, "请选择地址");
            }
            //查询用户选择的地址是否存在
            try {
                $address = (new MallUserAddress())->getBaseById($address_id);
            } catch (\Exception $e) {
                return Show::json_show(Status::mini_error, "订单错误");
            }
            if (empty($address)) {
                return Show::json_show(Status::mini_error, "所选地址不存在");
            }
        } else {
            $address = [
                "id" => 0,
                "realname" => "",
                "mobile" => "",
                "cityarea" => "",
                "locatarea" => "",
                "address" => ""
            ];
        }
        //查询订单是否存在 是否支付
        try {
            $order = $this->model->getOrderByOrderId($order_id);
        } catch (\Exception $e) {
            return Show::json_show(Status::mini_error, "订单错误");
        }
        if (!$order) {
            return Show::json_show(Status::mini_error, "订单不存在");
        }
        if ($order['status'] != 0) {
            return Show::json_show(Status::mini_error, "订单状态错误");
        }


        //查询优惠券
        $coupon_money = 0;
        if ($coupon_id != 0) {
            if ($order['is_coupon'] != 1) {
                //查询优惠券是否正常 不正常
                try {
                    $coupon = $this->getCoupon($coupon_id, $order['id'], $order['orderprice']);
                } catch (\Exception $e) {
                    return Show::json_show(Status::mini_error, $e->getMessage());
                }
                $coupon_money = $coupon['coupon']['face_val'] ?? 0;
            }
        }

        //根据订单号修改信息
        $order_price = $order['payprice'] - $coupon_money;
        if ($order_price < 0) {
            $order_price = 0;
        }
        //判断快递
        $ex_money = 0;  //需要增加的快递金额
        $ex_number = 0;  //需要支付的快递次数
        $ex_price = 0; //快递单价
        $ex_num = 0; //减少的快递次数
        $ex_type = 0;
        if (!empty($express)) {
            //查询配置
            $config = (new WeixinExpressConfig())->getBaseById(1);
            if ($config['money'] > $order['orderprice']) {

                $num = count($express);
                //查询剩余次数
                $exp = (new WeixinExpress())->getUserExpressSurplus($this->m_openid);
                if ($num > $exp) { //剩余次数不足
                    $ex_type = 4;
                    $n = $num - $exp;
                    $ex_num = $exp;
                    $ex_number = $n;
                    $ex_price = $config['price'];
                    $ex_money = $n * $config['price'];
                } else {
                    $ex_type = 1;
                    $ex_num = $num;
                }

            } else {
                $ex_type = 1;
            }
        }
        $update_data = [
            "discountprice" => $coupon_money,
            "payprice" => $order_price + $ex_money,
            "paytype" => 1,
            "address_id" => $address['id'],
            "realname" => $address['realname'],
            "mobile" => $address['mobile'],
            "address" => $address['cityarea'] . $address['locatarea'] . $address['address'],
            "remark" => $desc,
            "status" => 0,
            "express_number" => $ex_number,
            "express_price" => $ex_price
        ];
        //减少积分
        $integral = (new PointReceive())->getUserIntegralSurplus($this->m_openid);
        $money = 0;
        $int_number = 0;
        if (intval($integral) > 0) {
            $int_number = intval(intval($integral) / sysconfig('shop', 'order_integral'));
            $money = $int_number * 0.01;
            $update_data['payprice'] = $update_data['payprice'] - $money;
        }
        $update_data['discountprice'] = $update_data['discountprice'] + $money;
        if ($coupon_id != 0) {
            if ($order['is_coupon'] != 1) {
                $update_data['is_coupon'] = 1;
                $update_data['coupon_id'] = $coupon_id;
            }
        }
        if (!empty($express)) {
            $update_data['is_express'] = 1;
        }
        if ($type == 0) {
            $update_data['shippingtype'] = 1;
        } else if ($type == 1) {
            $update_data['shippingtype'] = 2;
        }
        $this->model->startTrans();
        $ret = "";
        try {
            $this->model->updateDataSave($order['id'], $update_data);
            if ($update_data['payprice'] > 0) {
                $url = (string)url('/pay/notify/index', [], true, true);
                $order_data = [
                    'body' => '购买商品',
                    'out_trade_no' => $order['ordersn'],
                    'total_fee' => $update_data['payprice'] * 100,
                    'spbill_create_ip' => $this->request->ip(), // 可选，如不传该参数，SDK 将会自动获取相应 IP 地址
                    'notify_url' => $url, // 支付结果通知网址，如果不设置则会使用配置里的默认地址
                    'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
                    'openid' => $this->m_openid,
                ];
                //设置交易结束时间
                $time = sysconfig('shop', 'order_time');
                $time = (int)$time ?? 15;
                $second = ($time * 60) - 30;
                $end_time = strtotime($order['create_time']) + $second;
                $order_data['time_expire'] = date('YmdHis', $end_time);
                //下单
                $ret = $this->payment($order_data);
                //修改使用优惠券
                (new CouponReceive())->updateDataSave($coupon_id, [
                    "update_time" => time(),
                    "status" => 1
                ]);
            }
            //如果输入了快递单号， 进行快递单号保存
            if (!empty($express)) {

                $res_id = (new WeixinExpressOrder())->insertSaveById([
                    "order_id" => Str::instance()->RandNumberStr(),
                    "order_sn" => $order['id'],
                    "openid" => $this->m_openid,
                    "status" => 0,
                    "pay_status" => 0,
                    "pay_number" => $ex_number,
                    "unit_price" => $ex_price,
                    "order_number" => count($express),
                    "shop_id" => $this->shop_id,
                    "express_number" => $ex_num,
                    "price" => $ex_money,
                    "pay_type" => $ex_type

                ]);
                $insert_order = [];
                foreach ($express as $v) {
                    $insert_order[] = [
                        "order_id" => $res_id,
                        "express" => $v,
                        "status" => 0
                    ];
                }
                (new WeixinExpressOrderList())->saveAll($insert_order);
            }
            //减少对应积分
            (new PointReceive())->insertSaveById([
                "type" => 4,
                "source_type" => 2,
                "number" => "-" . $int_number,
                "openid" => $this->m_openid,
                "order_id" => $order['ordersn']
            ]);
            $this->model->commit();
        } catch (\Exception $e) {
            Log::error($e->getMessage() . " " . $e->getFile() . " " . $e->getLine());
            $this->model->rollback();
            return Show::json_show(Status::mini_error, "内部异常！请重试");
        }
        if ($update_data['payprice'] == 0) {
            $result = $this->model->updateDataSave($order['id'], [
                "status" => 1,
                "paytime" => time(),
                "paytype" => 1,
            ]);
            if ($result) {
                return Show::json_show(Status::mini_normal, "ok");
            } else {
                return Show::json_show(Status::mini_error, "支付失败");
            }
        } else {
            return Show::json_show(Status::mini_normal, 'OK', Show::json_decode($ret));
        }
    }

    /**
     * @param array $order_data
     * @return mixed
     * @throws Exception
     * @throws \ReflectionException
     */
    protected function payment(array $order_data = [])
    {


        $arr = ArrClass::payAttr();
        $obj = ArrClass::initClass('wx', $arr, [], true);
        Log::info("===============用户下单===============");
        $result = $obj->order($order_data);
        Log::info("===============用户下单返回结果===============" . Show::json_encode($result));

        if ($result['return_code'] != 'SUCCESS' || $result['result_code'] != 'SUCCESS') {
            throw new Exception("系统下单错误");
        }
        Log::info("===============生成支付===============");
        return $obj->jssdk($result['prepay_id']);
    }

    /**
     * 查询我的订单列表
     * @return array|\think\response\Json
     * @throws Exception
     */
    public function getOrderTypeList()
    {
        $type = $this->request->param('type', 0, 'intval');
        $limit = $this->request->param('limit', 10, 'intval');
        $page = $this->request->param('page', 1, 'intval');

        $where = [
            ['deleted', '=', 0]
        ];
        if ($type === 10000) {
            $where[] = [
                ['shippingtype', '=', 2],
                ['status', 'not in', [0, 3]]
            ];
        } else if ($type == 10001) {
            $where[] = [
                ['is_evaluate', '=', 0],
                ['status', '=', 3],
            ];
        } else {
            if ($type != -1) {
                if ($type == 2) {
                    $where[] = [
                        ['status', '=', $type],
                        ['shippingtype', '=', 1]
                    ];
                } else {
                    $where[] = [
                        ['status', '=', $type],
                    ];
                }
            }
        }

        //查询订单
        try {
            $result = $this->model->getOrderByOpenidList($where, $this->m_openid, $limit);
        } catch (\Exception $e) {
            return Show::json_show(Status::mini_error, $e->getMessage());
        }
        $order = $result['data'];
        $lists = [];
        if (!empty($order)) {
            foreach ($order as $v) {
                if (!empty($v)) {
                    $goodsList = $this->goodsList($v);
                }
                $lists[] = $goodsList ?? [];
            }
        }
        $res = [];
        if (!empty($lists)) {
            foreach ($lists as $v) {
                $goods_data = array_column($v['goods_data'], 'list');
                $goods_lists = [];
                if (!empty($goods_data)) {
                    foreach ($goods_data as $vv) {
                        foreach ($vv as $vvv) {
                            $goods_lists[] = $vvv;
                        }
                    }
                }
                $res[] = [
                    "ordersn" => $v['ordersn'],
                    "status" => $v['status'],
                    "status_name" => $this->model->getStatusList()[$v['status']],
                    "create_time" => $v['create_time'],
                    "payprice" => $v['payprice'],
                    "list" => $goods_lists,
                    "count" => count($goods_lists),
                    "id" => $v['id']
                ];
            }
        }
        $result['data'] = $res;
        return Show::json_show(Status::mini_normal, 'ok', $result['data'], $result['total'], false, $result['last_page']);

    }

    /**
     * 我的订单请求支付
     * @return array|\think\response\Json
     */
    public function sendPayment()
    {
        $id = $this->request->param('id', 0, 'intval');
        if ($id == 0) {
            return Show::json_show(Status::mini_error, "订单错误");
        }
        try {
            $order = $this->model->getBaseById($id, 'id,status,payprice,ordersn');
        } catch (\Exception $e) {
            return Show::json_show(Status::mini_error, "操作失败");
        }
        if (empty($order)) {
            return Show::json_show(Status::mini_error, "订单不存在");
        }
        if ($order['status'] != 0) {
            return Show::json_show(Status::mini_error, "订单状态错误");
        }
        //下单
        $url = (string)url('/pay/notify/index', [], true, true);
        $order_data = [
            'body' => '购买商品',
            'out_trade_no' => $order['ordersn'],
            'total_fee' => $order['payprice'] * 100,
            'spbill_create_ip' => $this->request->ip(), // 可选，如不传该参数，SDK 将会自动获取相应 IP 地址
            'notify_url' => $url, // 支付结果通知网址，如果不设置则会使用配置里的默认地址
            'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
            'openid' => $this->m_openid,
        ];
        try {
            $ret = $this->payment($order_data);
        } catch (\Exception $e) {
            return Show::json_show(Status::mini_error, $e->getMessage());
        }
        return Show::json_show(Status::mini_normal, 'OK', Show::json_decode($ret));
    }

    /**
     * 取消订单
     * @return array|\think\response\Json
     */
    public function cancelOrder()
    {
        $order_id = $this->request->param('order_id', '', 'trim');
        if (empty($order_id)) {
            return Show::json_show(Status::mini_error, '订单错误');
        }
        try {
            $result = (new BusOrder())->getOrderByOrderIdInfo($order_id);
        } catch (\Exception $e) {
            return Show::json_show(Status::mini_error, $e->getMessage());
        }
        if ($result) {
            return Show::json_show(Status::mini_normal, "取消成功");
        } else {
            return Show::json_show(Status::mini_error, "取消失败");
        }
    }

    /**
     * 创建快递订单
     * @return array|\think\response\Json
     * @throws Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function setExpressInfo()
    {
        $value = $this->request->param('value');
        $value1 = $this->request->param('value1');
        $value2 = $this->request->param('value2');
        if (empty($value)) {
            return Show::json_show(Status::mini_error, "请输入快递单号");
        }
        $lists = [];
        foreach ($value as $k => $v) {
            $lists[$k] = $value[$k] . " - " . $value1[$k] . " - " . $value2[$k];
        }
        //dump(count($lists));exit();
        //查询次数
        $order_id = Str::instance()->create_trade_no();
        $insert_data = [
            "order_id" => $order_id,
            "openid" => $this->m_openid,
            "order_number" => count($lists),
            "shop_id" => $this->shop_id
        ];
        $num = (new WeixinExpress())->getUserExpressSurplus($this->m_openid);
        //查询订单配置
        $config = (new WeixinExpressConfig())->getBaseById(1);
        if (empty($config) || $config['price'] <= 0) {
            return Show::json_show(Status::mini_error, "订单错误");
        }
        $insert_data['unit_price'] = $config['price'];
        if ($num <= 0) { //没有
            //需要支付金额
            $insert_data['pay_status'] = 0;
            $insert_data['pay_type'] = 3;
            $insert_data['express_number'] = 0;
            $insert_data['pay_number'] = count($lists);
            $insert_data['price'] = count($lists) * $config['price'];

        } else if ($num > 0 && $num < count($lists)) { //有 但是不足
            //需要补差价
            $number = count($lists) - $num;
            $insert_data['pay_status'] = 0;
            $insert_data['pay_type'] = 4;
            $insert_data['pay_number'] = $number;
            $insert_data['price'] = $number * $config['price'];
            $insert_data['express_number'] = $num;
        } else if ($num >= count($lists)) {
            //不需要支付
            $insert_data['pay_status'] = 0;
            $insert_data['pay_type'] = 1;
            $insert_data['pay_number'] = count($lists);
            $insert_data['price'] = 0;
            $insert_data['express_number'] = count($lists);
        }

        //增加快递单 减少单号

        $obj_express_order = new WeixinExpressOrder();
        //增加事务
        $obj_express_order->startTrans();
        try {
            $res_order = $obj_express_order->insertSaveById($insert_data);
            if ($res_order) {
                $lists_insert = [];
                foreach ($lists as $v) {
                    $lists_insert[] = [
                        "order_id" => $res_order,
                        "express" => $v,
                    ];
                }
                (new WeixinExpressOrderList())->saveAll($lists_insert);
            } else {
                throw new Exception("操作失败");
            }
            //减少快递次数
//            (new WeixinExpress())->insertSaveById([
//                "openid" => $this->m_openid,
//                "num" => "-".$insert_data['express_number']
//            ]);

            $obj_express_order->commit();
        } catch (\Exception $e) {

            $obj_express_order->rollback();
            return Show::json_show(Status::mini_error, $e->getMessage());
        }
        return Show::json_show(Status::mini_normal, "提交成功", [
            "order_id" => $order_id
        ]);
    }

    /**
     * @param array $express
     * @param string $order_id
     * @param float $money
     * @param array $address
     * @return bool|string
     * @throws Exception
     * @throws \ReflectionException
     */
    protected function setExpress(array $express = [], string $order_id = "", float $money = 0, array $address = [], string $desc = "")
    {
        if (empty($express)) {
            return true;
        }
        $shop = (new MallShop())->getBaseById($this->shop_id);


        if (empty($shop)) {
            return true;
        }
        $guid = \app\common\lib\Str::guid();
        $content = "<FS2><center>驿点生活 - {$shop['title']}</center></FS2>";
        $content .= str_repeat('.', 32);
//        $update_data = [
//            "address_id" => $address['id'],
//            "realname" => $address['realname'],
//            "mobile" => $address['mobile'],
//            "address" => $address['cityarea'] . " " . $address['locatarea'] . " " . $address['address'],
//            "update_time"=>time()
//        ];
        $content .= "联系人:" . $address['realname'] . "\n";
        $content .= "电话:" . $address['mobile'] . "\n";
        $content .= "地址:" . $address['address'] . "\n";
        $content .= "下单时间:" . date('Y-m-d H:i:s') . "\n";
        $content .= "订单编号:" . $order_id . "\n";
        $content .= "备注:" . $desc . "\n";
        //判断是那个店铺


        //获取快递单号
        $content .= str_repeat('*', 14) . "快递" . str_repeat("*", 14);
        //有快递
        if (!empty($express)) {
            $content .= "<table>";
            $content .= "<tr><td>快递取件码</td></tr>";
            foreach ($express as $v) {
                $content .= "<tr><td>{$v}</td></tr>";
            }
            $content .= "</table>";
            $content .= "快递数量:x" . count($express) . "\n";
            $content .= "快递金额:" . $money . "\n";
            $content .= str_repeat('*', 32);
        }


        $content .= str_repeat('*', 32);


        $url = request()->domain() . "/qrcode";
//        dump($url);exit();
        $content .= "<QR>{$url}</QR>" . PHP_EOL;


        //$content .= "<FS2><center>**#{$number} 完**</center></FS2>";
        $content .= "收藏”驿点生活小程序“" . "\n";
        $content .= "快递包裹/严选好物，替你送上门" . "\n";
        $content .= "客服电话：19112247033" . "\n";

        $send_data = [
            'machineCode' => $shop['express_id'],
            'content' => $content,
            'type' => 1,
            'id' => $guid,
            'openid' => $this->m_openid
        ];
        $result = $this->send($send_data);
        $send_data = [
            'machineCode' => sysconfig('shop', 'order_machine'),
            'content' => $content,
            'type' => 1,
            'id' => $guid,
            'openid' => $this->m_openid
        ];
        $result = $this->send($send_data);

        if ($result['code'] == Status::status_normal) {
            return "success";
        } else {
            return "fail";
        }
    }

    protected function send($send_data)
    {

        $obj = ArrClass::initClass(sysconfig('printer', 'print_type'), ArrClass::printer(), [["clientId" => sysconfig('printer', 'client_id'), "clientSecret" => sysconfig('printer', 'client_secret')]], true);
        $result = $obj->printer($send_data);
        return $result;
    }

    /**
     * @return array|\think\response\Json
     * @throws Exception
     */
    public function deleteOrder()
    {
        $order_id = $this->request->param('order_id', '', 'trim');
        if (empty($order_id)) {
            return Show::json_show(Status::mini_error, "订单不存在");
        }
        //
        $obj_model = new MallOrder();
        $row = $obj_model->getOrderByOrderId($order_id);

        if (empty($row)) {
            return Show::json_show(Status::mini_error, "订单不存在");
        }
        $res = $obj_model->updateDataSave($row['id'], [
            "deleted" => 1,
            "update_time" => time()
        ]);
        if ($res) {
            return Show::json_show(Status::mini_normal, "删除成功");
        } else {
            return Show::json_show(Status::mini_error, "删除失败");
        }
    }

    /**
     * @return array|\think\response\Json
     * @throws Exception
     */
    public function getOrderByInfo()
    {
        $order_id = $this->request->param('order_id', '', 'trim');
        if (empty($order_id)) {
            return Show::json_show(Status::mini_error, "订单号不存在");
        }
        //根据订单号查询订单
        $order = $this->model->getOrderByOrderId($order_id, 'id,ordersn,orderprice,payprice,status,discountprice,shippingtype,remark', 'coupon');
        if (!$order) {
            return Show::json_show(Status::mini_error, "商品不存在");
        }
        if ($order['status'] == 0) {
            return Show::json_show(Status::mini_error, "订单状态错误");
        }
        $order_data = $this->goodsList($order);
        return Show::json_show(Status::mini_normal, 'OK', $order_data);
    }

    /**
     * 确定收货
     * @return array|\think\response\Json
     * @throws Exception
     */
    public function setOrderSuccess()
    {
        $order_id = $this->request->param('order_id', '', 'trim');
        if (empty($order_id)) {
            return Show::json_show(Status::mini_error, "订单号不存在");
        }
        $order = $this->model->getOrderByOrderId($order_id, 'id,ordersn,orderprice,payprice,status,discountprice,shippingtype,remark');
        if (!$order) {
            return Show::json_show(Status::mini_error, "商品不存在");
        }
        if ($order['status'] == 0) {
            return Show::json_show(Status::mini_error, "订单状态错误");
        }
        //修改订单
        $result = $this->model->updateDataSave($order['id'], [
            "confirm_time" => time(),
            "status" => 3
        ]);
        if ($result) {
            return Show::json_show(Status::mini_normal, "收货成功");
        } else {
            return Show::json_show(Status::mini_error, "收货失败");
        }
    }

    public function setOrderRefund()
    {
        $order_id = $this->request->param('order_id', '', 'trim');
        if (empty($order_id)) {
            return Show::json_show(Status::mini_error, "订单号不存在");
        }
        $order = $this->model->getOrderByOrderId($order_id, 'id,ordersn,orderprice,payprice,status,discountprice,shippingtype,remark');
        if (!$order) {
            return Show::json_show(Status::mini_error, "商品不存在");
        }
        if ($order['status'] == 0) {
            return Show::json_show(Status::mini_error, "订单状态错误");
        }
        $result = $this->model->updateDataSave($order['id'], [
            "confirm_time" => time(),
            "status" => 4,
            "isapplyrefund" => 1,
            "isrefund" => 0
        ]);
        if ($result) {
            return Show::json_show(Status::mini_normal, "申请成功");
        } else {
            return Show::json_show(Status::mini_error, "申请失败");
        }
    }

    /**
     * 获取快递详情
     * @return array|\think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getOrderByExpress()
    {
        $order_id = $this->request->param('order_id', '', 'trim');
        if (empty($order_id)) {
            return Show::json_show(Status::mini_error, "订单不存在");
        }
        $order = (new WeixinExpressOrder())->getExpressByOrderIdByInfo($order_id);
        if (!$order) {
            return Show::json_show(Status::mini_error, "订单不存在");
        }
        if ($order['pay_status'] != 0) {
            return Show::json_show(Status::mini_error, "订单状态错误");
        }
        $order = $order->toArray();
        //查询订单
        $order_list = (new WeixinExpressOrderList())->getExpressByOrderId($order['id']);
        if (empty($order_list)) {
            return Show::json_show(Status::mini_error, "订单错误");
        }
        //查询默认地址
        $address = (new MallUserAddress())->getUserAddressByDefaultInfo($this->m_openid);
        $order['list'] = $order_list;
        $order['address'] = $address ?? [];
        return Show::json_show(Status::mini_normal, "ok", $order);
    }

    /**
     * @return array|\think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function submitExpressByOrder()
    {
        $order_id = $this->request->param('order_id', '', 'trim');
        $address_id = $this->request->param('address_id', 0, 'intval');
        $desc = $this->request->param('desc', '', 'trim');
        if (empty($order_id)) {
            return Show::json_show(Status::mini_error, "订单不存在");
        }
        if (empty($address_id) || $address_id == 0) {
            return Show::json_show(Status::mini_error, "请选择地址");
        }
        if (preg_match('/<(\w+)[^>]*>(.*?<\/\1>)?/', $desc)) {
            return Show::json_show(Status::mini_error, "备注格式错误");
        }
        $obj = new WeixinExpressOrder();
        $order = $obj->getExpressByOrderIdByInfo($order_id);
        if (!$order) {
            return Show::json_show(Status::mini_error, "订单不存在");
        }
        if ($order['pay_status'] != 0) {
            return Show::json_show(Status::mini_error, "订单状态错误");
        }
        $order = $order->toArray();
        //修改订单
        //根据id查询地址是否存在
        $address = (new MallUserAddress())->getBaseById($address_id);
        if (empty($address)) {
            return Show::json_show(Status::mini_error, "地址不存在");
        }
        $update_data = [
            "address_id" => $address['id'],
            "realname" => $address['realname'],
            "mobile" => $address['mobile'],
            "address" => $address['cityarea'] . " " . $address['locatarea'] . " " . $address['address'],
            "update_time" => time(),
            "description" => $desc
        ];
        $ret = $obj->updateDataSave($order['id'], $update_data);
        if (!$ret) {
            return Show::json_show(Status::mini_error, "请选择正确的地址");
        }
        if ($order['price'] > 0) {
            //直接下单支付
            $url = (string)url('/pay/notify/express', [], true, true);
            $order_data = [
                'body' => '快递配送费用',
                'out_trade_no' => $order['order_id'],
                'total_fee' => $order['price'] * 100,
                'spbill_create_ip' => $this->request->ip(), // 可选，如不传该参数，SDK 将会自动获取相应 IP 地址
                'notify_url' => $url, // 支付结果通知网址，如果不设置则会使用配置里的默认地址
                'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
                'openid' => $this->m_openid,
            ];
            try {
                $ret = $this->payment($order_data);
            } catch (\Exception $e) {
                return Show::json_show(Status::mini_error, $e->getMessage());
            }

            return Show::json_show(Status::mini_normal, 'OK', Show::json_decode($ret));
        } else {
            //直接修改订单

            $obj_d = new WeixinExpressOrder();
            //更新
            $obj_d->startTrans();
            try {
                $result = $obj_d->updateDataSave($order['id'], [
                    "pay_status" => 1,
                    "update_time" => time()
                ]);
                (new WeixinExpress())->insert([
                    "num" => "-" . $order['express_number'],
                    "openid" => $this->m_openid,
                    "source" => 3
                ]);
                $arr = (new WeixinExpressOrderList())->getExpressByOrderId($order['id']);
                $this->setExpress(array_column($arr, 'express'), $order['order_id'], $order['price'], $update_data, $desc);
                $obj_d->commit();
            } catch (\Exception $e) {
                $obj_d->rollback();
                Log::error($e->getMessage() . " " . $e->getFile() . " " . $e->getLine());
                return Show::json_show(Status::mini_error, "提交失败！请重试");
            }
            if ($result) {
                //直接打单

                return Show::json_show(Status::mini_normal, "ok", [
                    "type" => 1
                ]);
            } else {
                return Show::json_show(Status::mini_error, "操作失败");
            }
        }
    }

    /**
     * @return array|\think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getExpressOrderTypeList()
    {
        $type = $this->request->param('type', 0, 'intval');
        $limit = $this->request->param('limit', 10, 'intval');
        $page = $this->request->param('page', 1, 'intval');

        $where = [];
        switch ($type) {
            case -1:  //全部
                $where[] = [
                    ['pay_status', '<>', 0]
                ];
                break;
            case 0: //待付款
                $where[] = [
                    ['pay_status', '=', 0]
                ];
                break;
            case 1: //待配送
                $where[] = [
                    ['pay_status', '=', 1],
                    ['status', '=', 0]
                ];
                break;
            case 2: //已签收
                $where[] = [
                    ['pay_status', '=', 1],
                    ['status', '=', 1]
                ];
                break;
        }
        //查询订单
        try {
            $result = (new WeixinExpressOrder())->getOrderByOpenidList($where, $this->m_openid, $limit);
        } catch (\Exception $e) {
            return Show::json_show(Status::mini_error, $e->getMessage());
        }
        if (!empty($result)) {
            foreach ($result['data'] as $k => $v) {
                if ($v['pay_status'] == 0) {
                    $result['data'][$k]['status_name'] = "未支付";
                } else {
                    if ($v['status'] == 0) {
                        $result['data'][$k]['status_name'] = "未配送";
                    } else {
                        $result['data'][$k]['status_name'] = "已签收";
                    }
                }
                //查询商品
                $result['data'][$k]['list'] = (new WeixinExpressOrderList())->getExpressByOrderId($v['id']);
            }
        }
        return Show::json_show(Status::mini_normal, 'ok', $result['data'], $result['total'], false, $result['last_page']);

    }

    /**
     * 我的订单进行支付
     * @return array|\think\response\Json
     * @throws Exception
     * @throws \ReflectionException
     */
    public function submitPayment()
    {
        $order_id = $this->request->param('order_id', '', 'trim');
        $order = $this->model->getOrderByOrderId($order_id);
        if (!$order) {
            return Show::json_show(Status::mini_error, "订单不存在");
        }
        if ($order['status'] != 0) {
            return Show::json_show(Status::mini_error, "订单状态错误");
        }
        if ($order['address_id'] == 0) {
            return Show::json_show(Status::mini_error, "地址不全，无法支付");
        }
        $url = (string)url('/pay/notify/index', [], true, true);
        $order_data = [
            'body' => '购买商品',
            'out_trade_no' => $order['ordersn'],
            'total_fee' => $order['payprice'] * 100,
            'spbill_create_ip' => $this->request->ip(), // 可选，如不传该参数，SDK 将会自动获取相应 IP 地址
            'notify_url' => $url, // 支付结果通知网址，如果不设置则会使用配置里的默认地址
            'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
            'openid' => $this->m_openid,
        ];
        //设置交易结束时间
        $time = sysconfig('shop', 'order_time');
        $time = (int)$time ?? 15;
        $second = ($time * 60) - 30;
        $end_time = strtotime($order['create_time']) + $second;
        $order_data['time_expire'] = date('YmdHis', $end_time);

        $result = $this->payment($order_data);
        return Show::json_show(Status::mini_normal, "ok", Show::json_decode($result));
    }
}